package github.sf.fw.tools.tree.impl;




import github.sf.fw.tools.tree.BaseNode;
import github.sf.fw.tools.tree.BaseTreeNode;
import github.sf.fw.tools.tree.Node;
import github.sf.fw.tools.tree.TreeBuilder;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public abstract class BaseTreeBuilder implements TreeBuilder {
    private final Map<Object, Node> idAndNode = new HashMap<>();
    private final Map<Object, List<Node>> idAndChildNode = new HashMap<>();
    private final Map<Object, Node> idAndParentNode = new HashMap<>();

    /**
     * 存放树节点而不是数据库中结构的list
     */
    protected final List<Node> treeNodeList = new ArrayList<>();
    protected String treeNodeImpl;

    protected Node root;

    public void setTreeNodeImpl(String treeNodeImpl) {
        this.treeNodeImpl = treeNodeImpl;
    }

    @Override
    public void initialize(List<Node> nodes) {
        clearAll();
        nodes.stream().peek(node -> {
            Object nodeId = getNodeId(node);
            idAndNode.put(nodeId, node);
            putToIdAndChildNode(getParentId(node), node);
        }).forEach(node -> {
            if (BaseNode.class.isAssignableFrom(node.getClass())) {
                Node parentNode = idAndNode.getOrDefault(getParentId(node), null);
                idAndParentNode.put(getNodeId(node), parentNode);
            } else if (BaseTreeNode.class.isAssignableFrom(node.getClass())) {
                Node parentNode = idAndNode.getOrDefault(getParentId(node), null);
                idAndParentNode.put(getNodeId(node), parentNode);
            }
        });
    }

    /**
     * 传入节点中没有父节点的节点
     *
     * @return 根节点
     */
    public List<Node> getRoots() {
        List<Node> roots = new ArrayList<>();
        for (Map.Entry<Object, Node> entry : idAndParentNode.entrySet()) {
            if (entry.getValue() == null) {
                Object key = entry.getKey();
                Node node = idAndNode.get(key);
                if (node != null) {
                    roots.add(node);
                }
            }
        }
        return roots;
    }

    public Map<Object, Node> getIdAndNode() {
        return idAndNode;
    }

    public Map<Object, List<Node>> getIdAndChildNode() {
        return idAndChildNode;
    }

    public Map<Object, Node> getIdAndParentNode() {
        return idAndParentNode;
    }

    protected void clearTreeNodeList() {
        this.treeNodeList.clear();
    }

    protected void addNodeToTreeNodeList(Node node) {
        this.treeNodeList.add(node);
    }

    private Object getNodeId(Node node) {
        if (BaseNode.class.isAssignableFrom(node.getClass())) {
            return ((BaseNode) node).obtainNodeId();
        } else if (BaseTreeNode.class.isAssignableFrom(node.getClass())) {
            return ((BaseTreeNode) node).obtainNodeId();
        }
        throw new IllegalArgumentException("暂不支持当前Node类型：" + node.getClass());
    }

    private Object getParentId(Node node) {
        if (BaseNode.class.isAssignableFrom(node.getClass())) {
            return ((BaseNode) node).obtainParentId();
        } else if (BaseTreeNode.class.isAssignableFrom(node.getClass())) {
            return ((BaseTreeNode) node).obtainParentId();
        }
        throw new IllegalArgumentException("暂不支持当前Node类型：" + node.getClass());
    }

    private void putToIdAndChildNode(Object nodeId, Node child) {
        idAndChildNode.putIfAbsent(nodeId, new ArrayList<>());
        idAndChildNode.get(nodeId).add(child);
    }

    private void clearAll() {
        idAndNode.clear();
        idAndChildNode.clear();
        idAndParentNode.clear();
    }

    public List<Node> getTreeNodeList() {
        return treeNodeList;
    }

}
